#include "treedoc.h"
#include "macaction.h"
#include <QDebug>
#include <QTime>

TreeDoc::TreeDoc(DbConnection *db, QWidget *parent): QTreeWidget(parent),
    m_db(db),m_commonNumbering(true),m_macActionTypeFilter("outer"), m_macActionStateFilter("all"),m_highlight(false)
{
     setHeaderLabel(tr("Документы"));
     connect(this,SIGNAL(itemActivated(QTreeWidgetItem*,int)),this,SLOT(onNodeWakeUp(QTreeWidgetItem*)));
     connect(this,SIGNAL(itemExpanded(QTreeWidgetItem*)),this,SLOT(onNodeWakeUp(QTreeWidgetItem*)));
     connect(this,SIGNAL(itemClicked(QTreeWidgetItem*,int)),this,SLOT(onNodeWakeUp(QTreeWidgetItem*)));
     //connect(this,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(onNodeWakeUp(QTreeWidgetItem*)));
     connect(this,SIGNAL(itemCollapsed(QTreeWidgetItem*)),this,SLOT(onNodeWakeUp(QTreeWidgetItem*)));
     connect(this,SIGNAL(childWakeUp(DocEntity*)),this,SLOT(onItemRefresh(DocEntity*)));
}

DbConnection::QueryResult TreeDoc::execute(const QString &sql)
{
    return m_db->execute(sql);
}

void TreeDoc::refresh()
{
    if(isWasChangedItems())
    {
        QMessageBox box(this);
        box.setText(tr("Изменения будут потеряны. Продолжить?"));
        box.setIcon(QMessageBox::Question);
        box.setWindowTitle(tr("Обновление"));
        box.addButton(tr("Да"),QMessageBox::NoRole);
        QAbstractButton* no=box.addButton(tr("Нет"),QMessageBox::NoRole);
        box.exec();
        if(box.clickedButton()==no) return;
    }
    emit state_message(tr("Обновление документов. Пожалуйста подождите...."),0);
    while(topLevelItemCount()>0) delete takeTopLevelItem(0);
    DbConnection::QueryResult res=m_db->execute("select * from =schema=.ex_mac_actions");
    if(res.success())
    {
        bool MAFT = (m_macActionTypeFilter=="inner");
        for(int i=0;i<res.rows();i++)
        {
            MacAction* mac_action = new MacAction(res.at(i,4).toBool(),this);
            mac_action->blockSignals(true);
            mac_action->setID(res.at(i,0).toInt());
            mac_action->setNum(res.at(i,1).toInt());
            mac_action->setAuthor(m_users.user(res.at(i,2).toInt()));
            mac_action->setExpiry(res.at(i,3).toDate());
            mac_action->setHidden(mac_action->inner()!=MAFT);
            mac_action->setState(res.at(i,5).toInt());
            mac_action->blockSignals(false);
            if(m_highlight) turnOnHighlight(mac_action);
            QStringList ops = res.at(i,6).toString().replace(QRegExp("[{}]"),"").split(",",QString::SkipEmptyParts);
            if(ops.count()==0) continue;
            foreach(QString id,ops) mac_action->operations()->setEnabled(id.toInt(),true);
        }
    }
    emit state_message(tr("Обновление завершено."),10000);
}
void TreeDoc::removeItem(DocEntity *item)
{
    DocEntity* owner=0;
    if(item->parent()!=0) owner=item->parent();
    onSavedItem(item);
    delete item;
    if(owner==0)
        if(topLevelItemCount()>0)
            owner = dynamic_cast<DocEntity*>(topLevelItem(topLevelItemCount()-1));
    if(owner!=0) emit childWakeUp(owner);
}
void TreeDoc::setCommonNumbering(const bool &commonNumbering)
{
    m_commonNumbering=commonNumbering;
}
void TreeDoc::itemByFID(const QString &FID)
{
    QList<int>fid;
    foreach(QString eid,FID.split(":")) fid.append(eid.toInt());
    DocEntity* item=0;
    int index=0;
    bool found=false;
    while(index<topLevelItemCount()&&!found)
    {
        item=dynamic_cast<DocEntity*>(topLevelItem(index));
        found=item->id()==fid.at(0);
        index++;
    }
    if(!found) return;
    item->setExpanded(true);
    index=1;
    while((fid.at(index)!=0)&&(index<fid.count()))
    {
        DocEntity* Parent = item;
        found=false;
        int i=0;
        if(Parent->childCount()==0)Parent->giveBithTo();
        while(i<Parent->childCount()&&!found)
        {
            item = dynamic_cast<DocEntity*>(Parent->child(i));
            found = item->id()==fid.at(index);
            i++;
        }
        item->setExpanded(true);
        if(!found) return;
        index++;
    }
    emit childWakeUp(item);
}
QColor TreeDoc::colorFromString(const QString &color)
{
    bool ok;
    int red =tr("%1%2").arg(color.at(0)).arg(color.at(1)).toInt(&ok,16);
    int green=tr("%1%2").arg(color.at(2)).arg(color.at(3)).toInt(&ok,16);
    int blue =tr("%1%2").arg(color.at(4)).arg(color.at(5)).toInt(&ok,16);
    return QColor(red,green,blue);
}
bool TreeDoc::initialization()
{
    emit state_message(tr("Построение списка пользователей..."),Qt::AlignBottom,Qt::black);
    DbConnection::QueryResult res=execute("select * from =schema=.ex_users");
    if(res.success())
        for(int i=0;i<res.rows();i++)
            m_users.addUser(new User(res.at(i,0).toInt(),  res.at(i,1).toString(),res.at(i,2).toString(),
                                     res.at(i,3).toString(), res.at(i,4).toString(),
                                     res.at(i,5).toString(), res.at(i,6).toString()));
    else
    {
        emit state_message(tr("Аварийное завершение: не удалось посторить список пользователей."),Qt::AlignBottom,Qt::red);
        return false;
    }
    emit state_message(tr("Построение списка состояний документов..."),Qt::AlignBottom,Qt::black);
    res=execute("select * from =schema=.states where element_type>0");
    if(res.success())
    {
        for(int i=0;i<res.rows();i++)
        {
            m_statuses.insert(res.at(i,0).toInt(),res.at(i,2).toString());
            m_colors.insert(res.at(i,0).toInt(),res.at(i,3).toString());
        }
    }
    else
    {
        emit state_message(tr("Аварийное завершение: не удалось посторить список состояний документов."),Qt::AlignBottom,Qt::red);
        return false;
    }
    emit state_message(tr("Построение списка документов..."),Qt::AlignBottom,Qt::black);
    res=m_db->execute("select * from =schema=.ex_mac_actions");
    if(res.success())
    {
        bool MAFT = (m_macActionTypeFilter=="inner");
        for(int i=0;i<res.rows();i++)
        {
            MacAction* mac_action = new MacAction(res.at(i,4).toBool(),this);
            mac_action->blockSignals(true);
            mac_action->setID(res.at(i,0).toInt());
            mac_action->setNum(res.at(i,1).toInt());
            mac_action->setAuthor(m_users.user(res.at(i,2).toInt()));
            mac_action->setExpiry(res.at(i,3).toDate());
            mac_action->setHidden(mac_action->inner()!=MAFT);
            mac_action->setState(res.at(i,5).toInt());
            mac_action->blockSignals(false);
            if(m_highlight) turnOnHighlight(mac_action);
            QStringList ops = res.at(i,6).toString().replace(QRegExp("[{}]"),"").split(",",QString::SkipEmptyParts);
            if(ops.count()==0) continue;
            foreach(QString id,ops) mac_action->operations()->setEnabled(id.toInt(),true);
        }
    }
    else
    {
        emit state_message(tr("Аварийное завершение: не удалось посторить список документов."),Qt::AlignBottom,Qt::red);
        return false;
    }
    res = m_db->execute("select =schema=.in_uid()");
    if(res.success())
    {
        int id=res.at(0,0).toInt();
        res = m_db->execute("select current_time");
        if(res.success())
        {
            QTime time = res.at(0,0).toTime();
            QString hello=tr("Доброе утро");
            if(time.hour()>12) hello=tr("Добрый день");
            if(time.hour()>17) hello=tr("Добрый вечер");
            if(time.hour()>21) hello=tr("о_О");
            emit state_message(tr("%1 %2").arg(hello).arg(m_users.user(id)->name(User::SMName)),7000);
        }
    }
    return true;
}

UserList* TreeDoc::users()
{
    return &m_users;
}

void TreeDoc::onNodeWakeUp(QTreeWidgetItem *item)
{
    emit childWakeUp(dynamic_cast<DocEntity*>(item));
}
void TreeDoc::onItemRefresh(DocEntity *item)
{
    if(m_highlight) turnOnHighlight(item);
}
void TreeDoc::contextMenuEvent(QContextMenuEvent* event)
{
    DocEntity* item = dynamic_cast<DocEntity*>(itemAt(event->pos()));
    QMenu menu(this);
    if(item)
    {
        menu.addActions(item->operations()->list());
    }
    else
    {
        menu.addActions(filter(Scope));
        menu.addSeparator();
        menu.addActions(filter(State));
    }
    menu.exec(event->globalPos());
}
DbConnection* TreeDoc::db()
{
    return m_db;
}
void TreeDoc::appendMacAction(const bool &inner)
{
    int icount=0;
    if(m_commonNumbering)
    {
        icount=topLevelItemCount()+1;
    }
    else
    {
        for(int i=0;i<topLevelItemCount();i++)
            if(dynamic_cast<MacAction*>(topLevelItem(i))->inner()) icount++;
        icount=(inner)?icount+1:topLevelItemCount()-icount+1;
    }

    MacAction* item = new MacAction(inner,this);
    item->setID(0);
    item->setNum(icount);
    item->setExpiry(QDate::currentDate());
    item->setState(100);
    DbConnection::QueryResult res = execute(tr("select =schema=.in_uid()"));
    if(res.success()) item->setAuthor(users()->user(res.at(0,0).toInt()));
    item->operations()->setEnabled(2,true);
    item->operations()->setEnabled(5,true);
    item->operations()->setEnabled(9,true);
    turnOnHighlight(item);
    emit childWakeUp(item);
}
QString TreeDoc::statusByState(const int &state)
{
    return m_statuses.value(state,tr("Ошибка"));
}
QList<QAction*> TreeDoc::filter(const FilterType &filterType)
{
    QList<QAction*> filter;
    QActionGroup* group = new QActionGroup(parent());
    if(filterType==Scope)
    {
        QAction* action = new QAction(tr("Общезаводские КД/ПД"),parent());
        connect(action,SIGNAL(triggered()),this,SLOT(setMacActionTypeFilter()));
        action->setCheckable(true);
        action->setObjectName("outer");
        if(m_macActionTypeFilter=="outer") action->setChecked(true);
        group->addAction(action);
        filter.append(action);

        action = new QAction(tr("КД/ПД внутри подразделений"),parent());
        connect(action,SIGNAL(triggered()),this,SLOT(setMacActionTypeFilter()));
        action->setCheckable(true);
        group->addAction(action);
        action->setObjectName("inner");
        if(m_macActionTypeFilter=="inner") action->setChecked(true);
        filter.append(action);
    }
    if(filterType==State)
    {
        QAction* action = new QAction(tr("Все мероприятия"),parent());
        connect(action,SIGNAL(triggered()),this,SLOT(setMacActionStateFilter()));
        action->setCheckable(true);
        action->setObjectName("all");
        if(m_macActionStateFilter=="all") action->setChecked(true);
        group->addAction(action);
        filter.append(action);

        action = new QAction(tr("Разрабатываемые мероприятия"),parent());
        connect(action,SIGNAL(triggered()),this,SLOT(setMacActionStateFilter()));
        action->setCheckable(true);
        action->setObjectName("edited");
        if(m_macActionStateFilter=="edited") action->setChecked(true);
        group->addAction(action);
        filter.append(action);

        action = new QAction(tr("Выполняемые мероприятия"),parent());
        connect(action,SIGNAL(triggered()),this,SLOT(setMacActionStateFilter()));
        action->setCheckable(true);
        action->setObjectName("performed");
        if(m_macActionStateFilter=="performed") action->setChecked(true);
        group->addAction(action);
        filter.append(action);

        action = new QAction(tr("Завершенные мероприятия"),parent());
        connect(action,SIGNAL(triggered()),this,SLOT(setMacActionStateFilter()));
        action->setCheckable(true);
        action->setObjectName("completed");
        if(m_macActionStateFilter=="completed") action->setChecked(true);
        group->addAction(action);
        filter.append(action);

        action = new QAction(tr("Просроченные мероприятия"),parent());
        connect(action,SIGNAL(triggered()),this,SLOT(setMacActionStateFilter()));
        action->setCheckable(true);
        action->setObjectName("delinquent");
        if(m_macActionStateFilter=="delinquent") action->setChecked(true);
        group->addAction(action);
        filter.append(action);
    }
    return filter;
}
void TreeDoc::setMacActionTypeFilter()
{
    m_macActionTypeFilter=sender()->objectName();
    bool MAFT = (m_macActionTypeFilter=="inner");
    for(int i=0;i<topLevelItemCount();i++)
    {
        MacAction* item = dynamic_cast<MacAction*>(topLevelItem(i));
        item->setHidden(item->inner()!=MAFT);
    }
    setMacActionStateFilter("all");
    emit filterWasChange();
}
void TreeDoc::setMacActionStateFilter()
{
    setMacActionStateFilter(sender()->objectName());
    emit filterWasChange();
}
void TreeDoc::setMacActionStateFilter(const QString &filterName)
{
    m_macActionStateFilter=filterName;
    bool MAFT = (m_macActionTypeFilter=="inner");
    for(int i=0;i<topLevelItemCount();i++)
    {
        MacAction* mac_action=dynamic_cast<MacAction*>(topLevelItem(i));
        if(mac_action->inner()!=MAFT)continue;
        setItemsVisible(mac_action,filterName);
    }

}
void TreeDoc::setItemsVisible(DocEntity *item, const QString &filterName)
{
    if(filterName=="all") item->setHidden(false);
    if(filterName=="completed") item->setHidden(!item->isCompleted());
    if(filterName=="performed") item->setHidden(!item->isPerformed());
    if(filterName=="delinquent") item->setHidden(!item->isDelinquent());
    if(filterName=="edited") item->setHidden(!item->isEdited());
    for(int i=0;i<item->childCount();i++)
        setItemsVisible(dynamic_cast<DocEntity*>(item->child(i)),filterName);
}
bool TreeDoc::highlight() const
{
    return m_highlight;
}
void TreeDoc::setHighlight(const bool &on)
{
    m_highlight=on;
    for(int i=0;i<topLevelItemCount();i++)
        if(on)
            turnOnHighlight(dynamic_cast<DocEntity*>(topLevelItem(i)));
        else
            turnOffHighlight(dynamic_cast<DocEntity*>(topLevelItem(i)));
}
void TreeDoc::turnOnHighlight(DocEntity *item)
{
    if(!m_highlight)return;
    item->setColor(colorFromString(m_colors.value(item->state(),"#000000")));
    for(int i=0;i<item->childCount();i++)
        turnOnHighlight(dynamic_cast<DocEntity*>(item->child(i)));
}
void TreeDoc::turnOffHighlight(DocEntity *item)
{
    item->setColor(QColor(0,0,0));
    for(int i=0;i<item->childCount();i++)
       turnOffHighlight(dynamic_cast<DocEntity*>(item->child(i)));
}
void TreeDoc::onChangedItem(DocEntity *item)
{
    m_changedItems.append(item);
}
void TreeDoc::onSavedItem(DocEntity *item)
{
    int id=m_changedItems.indexOf(item);
    if(id>-1) m_changedItems.takeAt(id);
    for(int i=0;i<item->childCount();i++)
        onSavedItem(dynamic_cast<DocEntity*>(item->child(i)));
}
bool TreeDoc::isWasChangedItems() const
{
    return m_changedItems.count()!=0;
}
